home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / Mops 2.7 / Mops source / More classes / MW documents / MW3⁄4Mod.txt < prev    next >
Encoding:
Text File  |  1990-08-08  |  32.4 KB  |  1,454 lines  |  [TEXT/MSET]

  1. \ Word 3 and 4 documents.
  2.  
  3.     0    value    BUF_START
  4.     0    value    STLS        \ Holds copy of styles byte of current format
  5.     0    value    OPTIONS        \ Holds copy of options byte
  6.     0    value    DOING_PARAS?
  7.  
  8.  
  9. \ The following words handle the "change information" that is present if
  10. \ the document was saved using "Fast save".  This is fairly complicated,
  11. \ so we hope we've got it right.  If we don't recognize something, we set
  12. \ MYSTERY? true and put the code we didn't recognize into UNPROCESSED_CODE,
  13. \ so the application can warn the user that there may be problems.  These
  14. \ problems may be insignificant, which is why we don't give a hard error.
  15.  
  16.     0    value    #CHANGES
  17.     0    value    OPCODE        \ Holds op code for style etc. override
  18.     0    value    OVERRIDE_MARKER
  19.     0    value    NEW_CHANGE_BLK?
  20.     0    value    FMT_STRT
  21.     0    value    CHG-BLK?
  22.     0    value    CHGD-BLK?    \ True if previous offset was in a new chg blk
  23.     0    value    OV_BLK#
  24.  
  25. false    value    OV_ON?
  26.  
  27.  
  28. create  STYLES
  29. here
  30.   hex
  31.     80  c,        \ bold
  32.     40  c,        \ italic
  33.     20  c,        \ strikethru
  34.     10  c,        \ outline
  35.     08  c,        \ shadow
  36.     04  c,        \ small caps
  37.     02  c,        \ all caps
  38.     01  c,        \ hidden
  39.   decimal
  40. here swap -  constant    STYLES_LEN
  41.  
  42.  
  43. \         ============== Setting up ================
  44.  
  45. : LOCATE_NEW_CHANGE  { offs -- }
  46.     reset: changes
  47.     BEGIN
  48.         len: changes  0EXIT
  49.         offs  ^1st: changes @  <  ?EXIT
  50.         14 skip: changes
  51.     AGAIN   ;
  52.  
  53.  
  54.  
  55. local  FIX_OVERRIDE  { \ this_dst -- }
  56.  
  57. : SETUP_OFFSETS
  58.     true -> ov_on?        \ Forces generation of a fmt_ov_run entry to 
  59.                 \ turn overrides off at the start
  60.     tmp dup  copyto: src  copyto: dst
  61.     len: tmp  2/ 2/ 1- 3 /  -> #changes
  62.     #changes 1+ 4*  skip: src
  63.     4 nxtn: dst  -> this_dst
  64.     #changes 0
  65.     ?DO
  66.         pause
  67.         2 skip: src
  68.         4 nxtn: src  hdr_len -        \ source offset - save
  69.         dup  locate_new_change
  70.         2 nxtn: src  -> override_marker
  71.         ( this_dst ) fix_override    \ Note: uses PAD
  72.         pad !                \ source offset to PAD
  73.         4 nxtn: dst dup this_dst -  pad 4+ !    \ length
  74.         this_dst  pad 8 + !        \ dest offset
  75.         -> this_dst
  76.         override_marker  pad 12 + w!    \ override marker
  77.         pad 14  insert: changes        \ Move new entry in from PAD
  78.     LOOP  ;
  79.  
  80.  
  81. : SU_STYL_OV
  82.     nxtc: tmp
  83.     dup  $ 80 <>  and    \ 0 or $ 80 mean off, anything else means
  84.     0<> negate        \  on ... I hope ...
  85.     opcode  $ 1E  -  ^1st: fmt_ov_str  +  c!  ;
  86.  
  87. : SU_FONT_OV
  88.     2 nxtn: tmp  ^1st: fmt_ov_str  10 +  w!  ;
  89.  
  90. : SU_SIZ_OV
  91.     nxtc: tmp  2/  ^1st: fmt_ov_str  9 +  c!  ;
  92.  
  93. : SU_UND_OV
  94.     nxtc: tmp  2*  ^1st: fmt_ov_str  8 +  c!  ;
  95.  
  96. : SU_VD_OV
  97.     nxtc: tmp   dup  $ 80 =
  98.     IF  drop  0  THEN
  99.     ^1st: fmt_ov_str  12 +  c!   ;
  100.  
  101. : SU_HD_OV
  102.     nxtc: tmp  $ 40 -  2* 2*
  103.     ^1st: fmt_ov_str  13 +  c!  ;
  104.  
  105. : SU_PARA_OV1
  106.     1 skip: tmp  ;
  107.  
  108. \    opcode 5 =
  109. \    IF    nxtc: tmp  ^1st: para_ov_str  w!
  110. \    ELSE    1 skip: tmp           \ We're not handling these others
  111. \    THEN   ;
  112.  
  113. : SU_PARA_OV2
  114.     2 skip: tmp  ;
  115.  
  116. \    2 nxtn: tmp
  117. \    opcode dup $ 13 >= -  $ E - 2*  ^1st: para_ov_str +  w!   ;
  118.  
  119. : SU_STYL#_OV
  120.     nxtc: tmp
  121.     ^1st: para_ov_str ( 2+ )  w!  ;
  122.  
  123. : SU_OUTL_OV
  124.     nxtc: tmp  2+            \ outlining level no.
  125.     1 max  9 min            \ just in case
  126.     negate  $ FF  and  ^1st: para_ov_str ( 2+ )  w!  ;
  127.  
  128. : SU_SECT_OV
  129.     this_dst  +L: sect_ov_str  nxtc: tmp  +W: sect_ov_str  ;
  130.  
  131.  
  132. : SETUP_1_OVERRIDE
  133.     nxtc: tmp  dup  -> opcode
  134.     CASE[
  135.         $ 1E  $ 25    RANGE]=>    su_styl_ov
  136.      [  $ 05  $ 0B    RANGE]=>    su_para_ov1
  137.      [  $ 10  $ 15    RANGE]=>    su_para_ov2
  138.      [  $ 02    ]=>    su_styl#_ov
  139.      [  $ 04    ]=>    su_outl_ov
  140.      [  $ 0F    ]=>  ( tabs - we're ignoring them )
  141.                 nxtc: tmp ( length )  skip: tmp
  142.      [  $ 26    ]=>    su_font_ov
  143.      [ $ 27 ], [ $ 45 ]=>    su_und_ov    \ The 45 can come in W4 docs
  144.      [  $ 28    ]=>    su_siz_ov
  145.      [  0        ]=>    su_VD_ov
  146.      [  $ 29    ]=>    su_HD_ov
  147.      [  $ 41    ]=>    su_sect_ov
  148.      [  $ 1D    ]=>  ( pass - do nothing)
  149.     DEFAULT=> \ This means an opcode we don't know anything about.
  150.           \ So we set  MYSTERY? and skip to the end of the field.
  151.         -> unprocessed_code  true -> mystery?
  152.         lim: tmp >pos: tmp
  153.     ]CASE  ;
  154.  
  155.  
  156. : SETUP_OVERRIDES
  157.     pause
  158.     1 ++> ov_blk#
  159.     end: fmt_ov_str  pos: fmt_ov_str
  160.     pad  infoSize: fmt_run  2dup  128 fill  add: fmt_ov_str
  161.         \ set all fields to "leave" initially
  162.     >pos: fmt_ov_str
  163.     end: para_ov_str  pos: para_ov_str
  164.     pad  infoSize: para_run  2dup
  165.     bounds  DO   $ 8000  i w!   2 +LOOP
  166.     add: para_ov_str
  167.     >pos: para_ov_str
  168.     BEGIN
  169.         len: tmp 1 >
  170.     WHILE
  171.         setup_1_override
  172.     REPEAT  ;
  173.  
  174. : TURN_OV_OFF        \ ( dest -- )
  175.     false -> ov_on?
  176.     pad !
  177.     pad 4+  infoSize: fmt_run  128 fill
  178.     pad  itemSize: fmt_run  add: fmt_ov_run   ;
  179.  
  180.  
  181. :loc  FIX_OVERRIDE
  182.     override_marker  ov_on?  or  0EXIT    \ Out if we don't need an
  183.                         \ override entry here
  184.     override_marker  NIF  this_dst turn_ov_off  EXIT  THEN
  185.     true -> ov_on?
  186.     override_marker  $ 8000 and
  187.     NIF    \ It's immediate - create new ov str entries and make indirect.
  188.         save: tmp
  189.           src copyto: tmp
  190.           -2 skip: tmp  2 >len: tmp
  191.           setup_overrides        \ Actually, there's only 1
  192.         restore: tmp
  193.         ov_blk# 1-  $ 8000 or  -> override_marker
  194.     THEN
  195.         \ Now put new entry into FMT_OV_RUN
  196.     this_dst  +L: fmt_ov_run
  197.     infoSize: fmt_run  dup
  198.     override_marker $ 7FFF and *  >pos: fmt_ov_str  >len: fmt_ov_str
  199.     fmt_ov_str  $add: fmt_ov_run  ;loc
  200.  
  201.  
  202.  
  203. : SETUP_CHANGE        \ ( code -- )
  204.     CASE[ 1    ]=>    setup_overrides
  205.         [ 2    ]=>    setup_offsets
  206.       DEFAULT=>    -> unprocessed_code  true -> mystery?
  207.     ]CASE
  208.     lim: tmp >pos: tmp  ;
  209.  
  210.  
  211. \         ======= Applying the changes =======
  212.  
  213. : EXTEND_TEXT        \ Yes, this can happen, if changes insert stuff!
  214. \    pos: text  real_text_len  <=
  215. \    IF    \ Extending at or before the end.  Adjust real_text_len
  216. \        len: theFile  len: text -  ++> real_text_len
  217. \    THEN
  218.     pos: text  dup  len: theFile  +        \ Desired length
  219.     setsize: text  >pos: text  ;
  220.  
  221.  
  222. : CHANGE_TEXT
  223.     reset: text  reset: changes
  224.     0 -> text&hf_len
  225.     #changes 0 ?DO
  226.         nxtL: changes >pos: theFile
  227.         nxtL: changes >len: theFile
  228.         nxtL: changes >pos: text
  229.         len: theFile  len: text  >  IF  extend_text  THEN
  230.         theFile  $ovwr: text
  231.         pos: text   text&hf_len  max  -> text&hf_len
  232.         2 skip: changes  ( we don't use the override marker here )
  233.     LOOP
  234.     real_text_len text&hf_len max setsize: text  ;
  235.  
  236.  
  237. : FIND_OV_POSN
  238.     override_marker  ?dup  0EXIT
  239.     $ 7FFF and
  240.     infoSize: para_run *  >pos: para_ov_str  ;
  241.  
  242.  
  243. : FIND_PLACE  { offs -- }
  244.     BEGIN
  245.         len: changes  0EXIT
  246.         offs  ^1st: changes @  ^1st: changes 4+ @ +
  247.         doing_paras?  IF  <=  ELSE  <  THEN
  248.         ?EXIT
  249.         14 skip: changes
  250.     AGAIN  ;
  251.  
  252. : DIFFERENT_CHANGE_BLK  { offs -- }
  253.     offs find_place
  254.     len: changes
  255.     IF
  256.         ^1st: changes 12 + w@  -> override_marker
  257.         find_ov_posn
  258.     ELSE
  259.         0 -> override_marker
  260.     THEN  ;
  261.  
  262. : CHANGE_OFFSET  { offs -- offs' }    \ Returns -1 if offs is outside limits.
  263.     chg-blk? -> chgd-blk?
  264.     fast?         NIF   offs    EXIT  THEN
  265.     len: changes    NIF   -1    EXIT  THEN
  266.  
  267.     offs  ^1st: changes @  ^1st: changes 4+ @ +
  268.     doing_paras?  IF  >  ELSE  >=  THEN
  269.     dup -> chg-blk?
  270.     IF
  271.         offs  different_change_blk
  272.         len: changes  NIF  -1  EXIT  THEN
  273.     THEN
  274.     offs  ^1st: changes @  -
  275.     0 max                \ Coerce font change rightward
  276.                     \  after a deletion
  277.     ^1st: changes 8 + @  +  ;    \ Return transformed offset
  278.  
  279.  
  280. : OFF_FMTS        \ Inserts entries into fmt_run to turn formats
  281.             \ off at the end of change blocks.
  282.     fast?  0EXIT
  283.     reset: changes
  284.     BEGIN
  285.         len: changes
  286.         NIF
  287.             reset: fmt_run  reset: changes  EXIT
  288.         THEN
  289.         4 skip: changes
  290.         nxtL: changes  nxtL: changes +
  291.         dup  true  find_posn: fmt_run  new_item: fmt_run
  292.         styles_len 1+ skip: fmt_run
  293.         12 >nxtc: fmt_run  dflt_font# >nxtw: fmt_run
  294.         2 skip: changes
  295.     AGAIN  ;
  296.  
  297.  
  298. : ?DO_PARA_OVERRIDE        \ Note: para_run POS is at the start of the
  299.                 \ styles field.
  300.     override_marker  0EXIT
  301.     ^1st: para_ov_str  w@  dup  $ 8000 <>
  302.     IF  ^1st: para_run  w!  ELSE  drop  THEN  ;
  303.  
  304. \    pos: para_run
  305. \    infoSize: para_run  0  DO
  306. \        ^1st: para_ov_str i + w@  dup  $ 8000  <>
  307. \        IF  >nxtw: para_run  ELSE  drop  2 skip: para_run  THEN
  308. \    2 +LOOP
  309. \    >pos: para_run   ;
  310.  
  311.  
  312. \        ======= Miscellaneous useful words =======
  313.  
  314. : SETUP_BLKS    \ ( -- #blks )
  315.     theFile copyto: dst
  316.     len: dst  4-  6 /   ( # blks )
  317.     dup 1+ 4*  skip: dst
  318.     reset: changes   false -> chg-blk?  false -> chgd-blk?  ;
  319.  
  320. : NEXT_OFFS  { \ offs -- offs }
  321.     save_offs -> offs
  322.     unmpd_new -> unmpd_old
  323.     nxtl: buf  hdr_len -  dup -> unmpd_new
  324.     change_offset  -> save_offs
  325.     doing_paras?  NIF  offs  EXIT  THEN
  326.  
  327. \ For paras, we have to make sure that the incoming para offsets correspond
  328. \ to the RET chars in the text, since changes might have deleted or inserted 
  329. \ extra RETs.  We do this here.  What this amounts to is that we have to find
  330. \ the RET which begins the para immediately before where SAVE_OFFS points.
  331. \ We return the offs of this para (i.e. the offs of RET plus 1).
  332.  
  333.     start: text  save_offs 1 max  >lim: text  -1 more: text
  334.     RET  <chsearch: text  pos: text  swap -  ;  \ If RET found, skip it
  335.  
  336.  
  337. : NEXT_ITEM?    \ ( -- offs T | F )
  338.     next_offs
  339.     chgd-blk?
  340.     IF    dup  true  doing_paras?
  341.         IF    find_posn: para_run
  342.         ELSE    find_posn: fmt_run
  343.         THEN
  344.     THEN
  345.     ( offs )  dup  0>=  dup NIF  nip  1 skip: buf_offsets  THEN  ;
  346.  
  347.  
  348. \        ======== Merging formats ========
  349.  
  350. \ This isn't fun!!
  351.  
  352. : MERGE1  { offs -- }
  353.     offs  +L: fmt_run
  354.     pos: src  ( save )
  355.       4 skip: src  infoSize: fmt_run  >len: src
  356.       pos: fmt_run   src  $add: fmt_run   >pos: fmt_run
  357.     >pos: src  nolim: src
  358.     4 skip: fmt_ov_run
  359.     infoSize: fmt_run  0  DO
  360.         ^1st: fmt_ov_run i + c@  dup 128 <>
  361.         IF  >nxtc: fmt_run  ELSE  drop  1 skip: fmt_run  THEN
  362.     LOOP
  363.     ^1st: fmt_ov_run 10 + c@  128 <>
  364.     IF  ( kludge to make sure font# 128 works )
  365.         ^1st: fmt_ov_run 11 + c@   ^1st: fmt_run  3 -  c!
  366.     THEN
  367.     -4 skip: fmt_ov_run  ;
  368.  
  369.  
  370.     0    value    PREV        \ Holds offset in SRC of last entry read
  371.                 \ -- this is the one currently in effect
  372.  
  373.  
  374. : DO_LIMIT  { limit -- }    \ Generates new fmt_run entry for override
  375.                 \ change at the limit
  376.     skip_item: fmt_ov_run
  377.     prev 0<
  378.     IF  \ No SRC entry valid yet.  Just copy ov entry over
  379.         itemSize: fmt_run  >len: fmt_ov_run
  380.         fmt_ov_run  $add: fmt_run
  381.         nolim: fmt_ov_run
  382.     ELSE
  383.         prev  swappos: src
  384.             limit merge1
  385.           <skip_item: fmt_ov_run
  386.         >pos: src
  387.     THEN  ;
  388.  
  389. : MERGE_TO_LIMIT  { limit \ src-offs done? do-lim? -- }
  390.     false -> done?  false -> do-lim?
  391.     BEGIN
  392.         len: src
  393.         IF
  394.             ^1st: src @  -> src-offs
  395.             src-offs limit 2dup
  396.             > -> do-lim?  >= -> done?
  397.         ELSE
  398.         \ No formats left.  We may, however, have to generate a
  399.         \ fmt_run entry for the limit.  We only need to do this 
  400.         \ if it is a "real" (not a dummy) limit.
  401.  
  402.             limit big# <> -> do-lim?  true -> done?
  403.         THEN
  404.         do-lim?  IF  limit do_limit  EXIT  THEN
  405.         done?  ?EXIT
  406.         src-offs merge1
  407.         pos: src  -> prev   skip_item: src
  408.     AGAIN  ;
  409.  
  410. : (MERGE_FMTS)
  411.     -1 -> prev  ( means not valid yet )
  412.     BEGIN
  413.         pause
  414.         len: fmt_ov_run
  415.         NIF  ( no more overrides left - copy rest of src over )
  416.             src  $add: fmt_run  EXIT
  417.         THEN
  418.         len: src
  419.         NIF
  420.             <skip_item: src
  421.             BEGIN
  422.                 len: fmt_ov_run  0EXIT
  423.                 ^1st: fmt_ov_run @  merge1
  424.                 skip_item: fmt_ov_run
  425.             AGAIN
  426.         THEN
  427.         len: fmt_ov_run  itemSize: fmt_ov_run  >
  428.         IF    ^1st: fmt_ov_run  itemSize: fmt_ov_run  +  @
  429.         ELSE    big#
  430.         THEN
  431.         merge_to_limit
  432.         skip_item: fmt_ov_run
  433.     AGAIN  ;
  434.  
  435.  
  436. : MERGE_FMTS
  437.     fast?  0EXIT
  438.     reset: fmt_ov_run
  439.     len: fmt_ov_run  0EXIT      \ Out if nothing to merge
  440.     fmt_run  copyto: src  reset: src
  441.     new: fmt_run
  442.     (merge_fmts)            \ Do it
  443.     release: src  ;
  444.  
  445.  
  446. \        ======= Style sheet operations =======
  447.  
  448. \ The string of style names has the level names first, in reverse order,
  449. \ then any synonym(s) for "Normal" (empty if none), then the ordinary
  450. \ styles in forward order.
  451.  
  452. scon    NORM_STYLE "Normal"
  453.  
  454. hex
  455. table    DFLT_FONT
  456.     05001800 ,  dflt_font# c,  18 c,    \ Default: Geneva 12
  457. end_table
  458.  
  459. table    DFLT_PARA
  460. \    07000000 , 0 ,
  461.     03000000 ,
  462. end_table
  463. decimal
  464.  
  465.  
  466. : SKIP1NAME
  467. \    is1st# 255 of> style_names
  468.     1st: style_names  $ FF  =
  469.     IF    1 skip: style_names
  470.     ELSE    count: style_names  step: style_names
  471.     THEN  ;
  472.  
  473.  
  474. : COUNT_STYLES
  475.     reset: style_names  0 -> #styles
  476.     BEGIN
  477.         len: style_names
  478.     WHILE
  479.         skip1name  1 ++> #styles
  480.     REPEAT  ;
  481.  
  482.  
  483. : GET_STYLE_NAME  { n \ cnt -- addr len }    \ Exported.
  484.     n  NIF  norm_style  EXIT  THEN
  485.     reset: style_names  #levels negate  -> cnt
  486.     BEGIN
  487.         len: style_names  NIF  0 0  EXIT  THEN
  488.         cnt n =
  489.         IF
  490. \            is1st# 255 of> style_names  IF  0 0  EXIT  THEN
  491.             1st: style_names  $ FF  =  IF  0 0  EXIT  THEN
  492.             count: style_names  get: style_names  EXIT
  493.         THEN
  494.         skip1name
  495.         1 ++> cnt
  496.     AGAIN  ;
  497.  
  498.  
  499. : GET_STYLE#  { addr len \ n -- n }    \ Exported.
  500.         \ Maybe we should handle synonyms at some stage, if
  501.         \ anyone wants it.
  502.     addr len  norm_style  s=  IF  0  EXIT  THEN
  503.     reset: style_names  #levels negate  -> n
  504.     BEGIN
  505.         len: style_names
  506.         NIF  \ Put new style name in
  507.             len +: style_names
  508.             addr len  add: style_names
  509.             1 ++> #styles  n  EXIT
  510.         THEN
  511. \        is1st# 255 of> style_names
  512.         1st: style_names  $ FF  =
  513.         IF    1 skip: style_names
  514.         ELSE
  515.             count: style_names
  516.             get: style_names  addr len  s=
  517.             IF  n  EXIT  THEN
  518.             step: style_names
  519.         THEN
  520.         1 ++> n
  521.     AGAIN  ;
  522.  
  523.  
  524. : DUMMY_LEVEL_INFO
  525.     reset: style_names
  526.     pad #levels  2dup  -1 fill  add: src
  527.     #levels 0 ?DO  skip1name  LOOP  ;
  528.  
  529. : SS_FORMATS
  530.     dummy_level_info        \ Dummy formats
  531.     dflt_font  add: src        \ Default format for Normal style
  532.     skip1name            \ Skip Normal name
  533.     #styles #levels -  1  ?DO    \ Put in dummy formats
  534. \        is1st# 255 of> style_names
  535.         1st: style_names  $ FF  =
  536.         IF    $ FF  +c: src   1 skip: style_names
  537.         ELSE
  538.             0 +c: src
  539.             count: style_names  step: style_names
  540.         THEN
  541.     LOOP
  542.     reset: src  len: src  2+  2 +n: dst  src  $add: dst   ;
  543.  
  544. : SS_PARAS
  545.     clear: src
  546.     dummy_level_info
  547.     #styles #levels -  0  ?DO
  548. \        is1st# 255 of> style_names
  549.         1st: style_names  $ FF  =
  550.         IF    $ FF  +c: src   1 skip: style_names
  551.         ELSE
  552.             dflt_para  add: src
  553.             i  ^1st: src  3 -  c!
  554.             count: style_names  step: style_names
  555.         THEN
  556.     LOOP
  557.     reset: src  len: src  2+  2 +n: dst  src  $add: dst  ;
  558.  
  559.  
  560. : SETUP_STYLE_SHEET
  561.     new: src  new: dst
  562.     size: style_names
  563.     IF
  564.         count_styles
  565.     ELSE    \ There must be at least a "normal" style, or Word will
  566.         \ crash!  So we'll put one in.
  567.         0 +c: style_names  1 -> #styles
  568.     THEN
  569.     reset: style_names
  570.     #levels  +W: dst  len: style_names  2+  +W: dst
  571.     style_names  $add: dst
  572.     ss_formats
  573.     ss_paras
  574.     #styles  2 +N: dst
  575.     pad  #levels 2*  2dup erase  add: dst  $ 00DE  2 +n: dst
  576.     #styles #levels - 1-  0 ?DO  0  2 +n: dst  LOOP
  577.     reset: dst  release: src  ;
  578.  
  579. : NEED_LEVEL  { lev# \ n -- }
  580.         \ Exported.  Ensures that the number of levels we
  581.         \ have is at least lev#.
  582.  
  583.     lev# #levels -  -> n
  584.     n  0<=  ?EXIT
  585.     start: style_names
  586.     pad n  2dup  -1 fill  insert: style_names
  587.     lev# -> #levels  ;
  588.  
  589. \        ==============================
  590.  
  591. :class  SD    super(  object  )
  592.  
  593.     var    START
  594.     int    LENGTH
  595.  
  596. :m  GET:  get: start  get: length  ;m
  597. :m  PUT:  put: length  put: start  ;m
  598. :m  USE:  get: self  swap  hdr_len -  >pos: theFile  >len: theFile  ;m
  599.  
  600.  
  601. ;class
  602.  
  603.  
  604. table  FOR_STRC
  605.   hex    2 w, 3 w, 4 w, 5 w, 10 w, 14 w, 1D w, C9 w, F1 w, F3 w,
  606. end_table   decimal
  607.  
  608. table    DFLT_P
  609.     0 w,  0 c,
  610. end_table
  611.  
  612.  
  613. :class MW3DOC    super(  object  )
  614.  
  615.     int    MARKER
  616.    8    bytes    xx1
  617.     int    FAST_SAVE?
  618.     int    xx2
  619.     var    TX_END_OFFS
  620.   12    bytes    xx3
  621.     sd    STYLES_STR1
  622.     sd    STYLES_STR2
  623.     sd    FTN_MARKER_STR
  624.     sd    FTN_OFFSET_STR
  625.     sd    SECTOFFS_STR
  626.     sd    Str4
  627.     sd    Str5
  628.     sd    Str6
  629.     sd    HFOFFS_STR
  630.     sd    FMT_BLK_STR
  631.     sd    PARA_BLK_STR
  632.     sd    Str8
  633.     sd    StrC
  634.     sd    Str9
  635.     sd    CHANGE_STR
  636.     var    TEXT_START
  637.     var    TEXT_LENGTH
  638.     var    FOOTNOTE_LEN
  639.     var    HF_LEN
  640.   36    bytes    xx6
  641.     int    PAPER_HT
  642.     int    PAPER_WDTH
  643.     int    T_MARGIN
  644.     int    L_MARGIN
  645.     int    B_MARGIN
  646.     int    R_MARGIN
  647.     var    MAGIC3
  648.     int    PAGE_OPTIONS
  649.     int    MAGIC5
  650.     int    MAGIC6
  651.     int    MAGIC7
  652.     int    HOW_PRINT?
  653.   58    bytes    EMPTY
  654.     
  655.  
  656.  
  657. :m CLR_BUF:
  658.     reset: buf  all: buf  erase  ;m
  659.  
  660. :m SET_BUF:    \ ( blk# -- )
  661.     theFile  copyto: buf
  662.     2-  7 <<  dup  >pos: buf  -> buf_start
  663.     128 >len: buf
  664.     buf copyto: buf_offsets  buf copyto: buf_tmp   ;m
  665.  
  666. :m BUF_OUT:
  667.     all: buf  write: theFcb  OK?  ;m
  668.  
  669.  
  670. :m SETUP_CHANGES:  { \ this_dst -- }
  671.     clear: changes  clear: fmt_ov_str  0 -> override_marker
  672.     fast?  0EXIT
  673.     0 -> ov_blk#
  674.     use: change_str  theFile copyto: tmp
  675.     BEGIN
  676.         len: tmp  0>  ( a bug could make it negative!!! )
  677.     WHILE
  678.         nxtc: tmp  ( opcode )
  679.         2 nxtn: tmp  >len: tmp
  680.         setup_change
  681.         lim: theFile  >lim: tmp
  682.     REPEAT
  683.     reset: changes  reset: fmt_ov_str
  684.     ^1st: changes 12 + w@  -> override_marker  ( initial value )
  685.     find_ov_posn  ;m
  686.  
  687. :m TEXT_IN:
  688.     pause
  689.     text&HF_len  setsize: text
  690.     fast?
  691.     IF    change_text
  692.     ELSE    reset: text
  693.         get: text_start  hdr_len -  >pos: theFile  nolim: theFile
  694.         theFile $ovwr: text  reset: text
  695.     THEN
  696.     text_only?  0EXIT
  697.     real_text_len  setsize: text  reset: text  ;m
  698.  
  699.  
  700. :m GET_FONT:        \ ( -- fnt# )
  701.     options  $ 10  and
  702.     NIF  dflt_font#  ELSE  fmt 3+ 2b@  THEN
  703.     >nxtw: fmt_run   ;m
  704.  
  705. :m GET_FONTSIZE:    \ ( -- n )
  706.     options  8 and
  707.     NIF  12  ELSE  fmt 5 + c@  2/  THEN
  708.     >nxtc: fmt_run   ;m
  709.  
  710. :m GET_FIELD:        \ ( offs -- )
  711.     fmt + c@  ( optional field )
  712.     >nxtc: fmt_run   ;m
  713.  
  714. :m GET_FMT:  { offs -- }
  715.  
  716.         \ Converts the current format to our internal coding
  717.         \ and inserts it in FMT_RUN.
  718.  
  719.     fmt 1+ c@  -> stls  fmt 2+ c@  dup -> options
  720.     $ 40 and  IF  offs  spec_in  EXIT  THEN
  721.     offs new_item: fmt_run
  722.     pos: fmt_run  -> fmt_strt
  723.     styles styles_len  bounds
  724.     DO
  725.         i c@  ( mask )  stls and 0<>  ( 1 set, 0 clear )
  726.         >nxtc: fmt_run
  727.     LOOP
  728.     8  get_field: self  ( underline options )
  729.     get_fontsize: self
  730.     get_font: self
  731.     6  get_field: self  ( vert displ )
  732.     7  get_field: self  ( horiz displ )   ;m
  733.  
  734. :m (FMT_IN):  { \ offs -- }
  735.     next_item?  0EXIT
  736.     -> offs
  737.     fmt  fmt_len  erase
  738.     nxtc: buf_offsets  ?dup
  739.     IF    buf_start +  >pos: buf_tmp
  740.         ^1st: buf_tmp  fmt  over c@ 1+  cmove
  741.     THEN
  742.     offs  get_fmt: self   ;m
  743.  
  744. :m (FMT_BLK_IN):    \ ( cnt -- )
  745.     2 nxtn: fmt_blk#s  set_buf: self
  746.     NIF  next_offs drop  ELSE  4 skip: buf  THEN
  747.     last: buf  ( # formats )
  748.     dup 1+ 4*  skip: buf_offsets
  749.     0 ?DO    (fmt_in): self
  750.     LOOP   ;m
  751.  
  752. :m FMTS_IN:
  753.     false -> doing_paras?
  754.     use: fmt_blk_str  setup_blks  -> #fmt_blks
  755.     dst copyto: fmt_blk#s
  756.     off_fmts
  757.     #fmt_blks 0 DO  pause  i  (fmt_blk_in): self   LOOP
  758.     merge_fmts  trim_fmt_run   ;m
  759.  
  760. :m GET_PARA:  { \ addr code -- }
  761.     ^1st: para_run  -> addr
  762.     nxtc: buf_tmp  addr  w!  ;m        \ style #
  763.  
  764.  
  765. :m (PARA_IN):
  766.     next_item?  0EXIT
  767.     ( offs )  new_item: para_run
  768.     nxtc: buf_offsets  ?dup
  769.     IF
  770.         buf_start +  >pos: buf_tmp  count: buf_tmp
  771.         get_para: self
  772.     THEN
  773.     ?do_para_override
  774.     ?keep_para   ;m
  775.  
  776. :m (PARA_BLK_IN):    \ ( cnt -- )
  777.     2 nxtn: para_blk#s  set_buf: self
  778.     NIF  next_offs drop  ELSE  4 skip: buf  THEN
  779.     last: buf  ( # paras )
  780.     dup 1+ 4*  skip: buf_offsets
  781.     0 DO    (para_in): self
  782.     LOOP   ;m
  783.  
  784. :m PARAS_IN:
  785.     true -> doing_paras?
  786.     use: para_blk_str  setup_blks  -> #para_blks
  787.     dst copyto: para_blk#s
  788.     #para_blks 0 DO  pause  i  (para_blk_in): self  LOOP   ;m
  789.  
  790.  
  791. :m STYLES_IN:    \ Note: we ignore input style specifications, and just
  792.         \ hang on to the names.
  793.     pause
  794.     use: styles_str2
  795.     2 nxtn: theFile  -> #levels
  796.     2 nxtn: theFile  2-  >len: theFile
  797.     theFile  ->: style_names  ;m
  798.  
  799.  
  800. :m HFs_IN:
  801.     use: sectoffs_str  theFile ->: sect_offsets
  802.     use: HFoffs_str  mark_HFs  ;m
  803.  
  804.  
  805. :m FTNOTES_IN:        \ Footnotes in.  Sorry for funny name - we had
  806.             \ a hash collision.
  807.     ftn_len  0EXIT            \ Out if no footnotes
  808.     use: ftn_marker_str  theFile ->: ftn_markers
  809.     use: ftn_offset_str  theFile ->: ftn_offsets
  810.     mark_ftn  ;m
  811.  
  812.  
  813. :m SETUP_INPUT:
  814.     pause
  815.     new: theFile  new: changes
  816.     new: fmt_ov_str  new: fmt_ov_run
  817.     new: para_ov_str  new: sect_offsets  new: sect_ov_str
  818.     new: ftn_markers  new: ftn_offsets
  819.     false -> mystery?  0 -> #insrtd  0 -> save_offs
  820.     ^base 2+  hdr_len 2-  read: theFcb  OK?
  821.     get: fast_save?   -> fast?
  822.     get: text_length  -> real_text_len
  823.     get: tx_end_offs  hdr_len -  -> text&HF_len
  824.     get: page_options $ 8000 and 0<>  -> facing_pages?
  825.     text&HF_len  ++> mem_needed
  826.     get: footnote_len  -> ftn_len
  827.     text_only?  ?EXIT
  828.     size: theFcb  hdr_len -  text&HF_len -
  829.     3 *  0 max        \ Guesstimate for size of fmt_run etc.
  830.     ++> mem_needed  ;m
  831.  
  832.  
  833. :m INPUT_FILE:
  834.     pause
  835.     theFcb
  836.     size: theFcb  hdr_len -  readn: theFile  ;m
  837.  
  838.  
  839. :m FIXIT:
  840.     setup_changes: self
  841.     text_in: self
  842.     text_only?
  843.     NIF
  844.         fmts_in: self
  845.         paras_in: self
  846.         styles_in: self
  847.         ftnotes_in: self
  848.         HFs_in: self
  849.     THEN  ;m
  850.  
  851.  
  852. :m WINDUP_INPUT:
  853.     release: theFile  release: changes
  854.     release: fmt_ov_str  release: fmt_ov_run
  855.     release: para_ov_str  release: sect_offsets
  856.     release: sect_ov_str
  857.     release: ftn_markers  release: ftn_offsets  ;m
  858.  
  859.  
  860. \        ========== Output ===========
  861.  
  862. :m SETUP_OUTPUT:
  863.     ^base hdr_len  2dup  erase  write: theFcb  OK?  ( dummy header )
  864.     new: buf  128 setsize: buf  clr_buf: self
  865.     new: buf_offsets  new: fmt_blk#s  new: para_blk#s
  866.     new: para_tmp  new: hf_offsets  new: sect_offsets
  867.     new: ftn_markers  new: ftn_offsets
  868.     0 -> #fmt_blks  0 -> #para_blks  false -> GHF?
  869.       \ Now we set the default format - leave zero so style sheet
  870.       \ determines everything.
  871.     fmt  fmt_len erase  ;m
  872.  
  873.  
  874. :m (NEW_BLK):
  875.     clr_buf: self  -1 more: buf
  876.     clear: buf_offsets
  877.     save_offs  hdr_len +  >nxtl: buf
  878.     0 -> #entries  ;m
  879.  
  880. :m (WRITE_BLK):
  881.     all: buf_offsets  >nxt$: buf  clear: buf_offsets
  882.     #entries  all: buf + 1- c!
  883.     buf_out: self  (new_blk): self  ;m
  884.  
  885. :m WRITE_BLK:
  886.     pause
  887.     all: buf drop @  +L: blk#s
  888.     (write_blk): self  1 ++> #blks   ;m
  889.  
  890.  
  891. :m MATCH?:  { addr len -- b }
  892.     true -> case?
  893.     buf  copyto: tmp
  894.     step: tmp
  895.     false   len  0EXIT
  896.     BEGIN
  897.         len: tmp  1 <= ?EXIT
  898.         count: tmp
  899.         addr len  compare: tmp
  900.         NIF  ( match occurred )  drop true
  901.             pos: tmp  1-  +c: buf_offsets  EXIT
  902.         THEN
  903.         step: tmp
  904.     AGAIN  ;m
  905.  
  906. :m STR_OUT:  { offs addr len \ matched? bo_len -- }
  907.     false -> matched?
  908.     all: buf_offsets -> bo_len  drop
  909.     len: buf  bo_len -  5 <
  910.     IF    write_blk: self
  911.     ELSE    addr len  match?: self  dup -> matched?
  912.         NIF    len: buf  bo_len -  len 6 +  <
  913.             IF   write_blk: self   THEN
  914.         THEN
  915.     THEN
  916.     1 ++> #entries
  917.     offs -> save_offs
  918.     offs hdr_len +  >nxtl: buf
  919.     matched?  ?EXIT
  920.     len
  921.     IF    len 1+ negate  more: buf
  922.         lim: buf  +c: buf_offsets
  923.         buf copyto: tmp
  924.         step: tmp
  925.         len  >nxtc: tmp  addr len  >nxt$: tmp
  926.     ELSE
  927.         0  +c: buf_offsets
  928.     THEN  ;m
  929.  
  930.  
  931. :m SET_FIELD:  { n dflt mask offs -- }
  932.     n 128 =  ?EXIT            \ No action if "leave" specified
  933.     mask  fmt 2+
  934.     n dflt =
  935.     IF    creset  0
  936.     ELSE    cset    n
  937.         mask 8 =  IF  2*  THEN    \ must double font size
  938.     THEN
  939.     fmt offs +  c!   ;m
  940.  
  941. :m SET_FONT:  { \ font# -- }
  942.     nxtw: fmt_run  -> font#
  943.     font# $ 8000 and  ?EXIT        \ Out if "leave"
  944.     $ 10  fmt 2+
  945.     font# dflt_font#  =
  946.     IF    creset  0
  947.     ELSE    cset    font#
  948.     THEN
  949.     fmt 3 +  2b!  ;m
  950.  
  951. :m SET_FMT_LEN:
  952.     8  fmt 1+  fmt 8 +
  953.     DO    i c@  IF  LEAVE  ELSE  1-  THEN
  954.     -1 +LOOP
  955.     fmt c!   ;m
  956.         
  957. :m CHK_SPEC:        \ ( -- b )  Returns FALSE if this format is not
  958.             \ a special, so SET_FMT: will handle it.
  959.     BEGIN
  960.         ^1st: fmt_run 10 + w@        \ Font # or graphics flag
  961.         $ FFFF =  0dup  0EXIT        \ Out if font #
  962.         handle_spec  str_out: self
  963.         skip_info: fmt_run
  964.         len: fmt_run  0=  ?dup  ?EXIT
  965.         ^1st: fmt_run @  save_offs  <>  ?dup  ?EXIT
  966.       \ Next format has same offset.  So we loop to process it now.
  967.         4 skip: fmt_run
  968.     AGAIN   ;m
  969.  
  970. :m SET_FMT:
  971.     chk_spec: self  ?EXIT    \ Out if "format" was a special
  972.     styles styles_len  bounds
  973.     DO    i c@  ( mask )
  974.         nxtc: fmt_run  ( 0 = clear, 128 = leave, anything else = set )
  975.         dup 128 =
  976.         IF    2drop
  977.         ELSE
  978.             IF    ( set )    fmt 1+  cset
  979.             ELSE  ( clear )  fmt 1+  creset
  980.             THEN
  981.         THEN
  982.     LOOP
  983.     \ Parms for set_field:    n dflt mask offs
  984.     nxtc: fmt_run  ( undl )          0  $ 04  8  set_field: self
  985.     nxtc: fmt_run  ( size )       0  $ 08  5  set_field: self
  986.     set_font: self
  987.     nxtc: fmt_run  ( v displ )    0  $ 02  6  set_field: self
  988.     nxtc: fmt_run  ( h displ )    0  $ 01  7  set_field: self
  989.     set_fmt_len: self  ;m
  990.  
  991.  
  992. :m (FMT_OUT):    \ ( offs -- )
  993.     fmt count  str_out: self   ;m
  994.  
  995. :m FMT_OUT:    \ ( offs -- )
  996.    \ Note: we don't o/p default format if fmt_run starts with a zero offset.
  997.     ?dup IF  (fmt_out): self  THEN
  998.     set_fmt: self  ;m
  999.  
  1000. :m SET_PARA:
  1001.     3 setsize: para_tmp   reset: para_tmp
  1002. \    nxtw: para_run  ( justification - save )
  1003.     nxtw: para_run  ( style # )  >nxtc: para_tmp
  1004.     0 pad !  pad 2  >nxt$: para_tmp
  1005. \    ( justif. )  ?dup IF  5 +c: para_tmp  +c: para_tmp  THEN
  1006. \    $ 12  $ 10  DO
  1007. \        nxtw: para_run
  1008. \        ?dup IF   i  +c: para_tmp  2 +n: para_tmp   THEN
  1009. \    LOOP
  1010. \    $ 16  $ 13  DO
  1011. \        nxtw: para_run
  1012. \        ?dup IF   i  +c: para_tmp  2 +n: para_tmp   THEN
  1013. \    LOOP
  1014.     all: para_tmp  dflt_p  s=  0EXIT
  1015.     ( It's a default para )  clear: para_tmp  ;m
  1016.  
  1017. :m PARA_OUT:  { offs -- }
  1018.     offs para_offs >
  1019.     IF
  1020.         set_para: self  offs next_para
  1021.     THEN
  1022.     offs  all: para_tmp  str_out: self  ;m
  1023.  
  1024.  
  1025. :m TEXT_OUT:
  1026.     pause
  1027.     reset: text
  1028.     len: text  -> total_text_len
  1029.     hdr_len  moveto: theFcb  OK?
  1030.     get: text  write: theFcb  OK?
  1031.     total_text_len  hdr_len +  -> buf_start
  1032.         \ Now pad out written text to 128-byte multiple
  1033.     len: text  127 and  ?dup
  1034.     IF    128 swap -  dup ++> buf_start
  1035.         pad swap  write: theFcb  OK?
  1036.     THEN  ;m
  1037.  
  1038.  
  1039. :m FMTS_OUT:
  1040.     fmt_blk#s  copyto: blk#s
  1041.     mark_original: blk#s        \ Safe - see end of defn
  1042.     0 -> #blks  0 -> save_offs  (new_blk): self  reset: fmt_run
  1043.     BEGIN   len: fmt_run
  1044.     WHILE
  1045.         nxtl: fmt_run  fmt_out: self
  1046.     REPEAT
  1047. \    real_text_len  (fmt_out): self        \ **************
  1048.     GHF?  IF  GHF_formats_out  THEN
  1049.     write_blk: self  save_offs hdr_len +  +L: blk#s
  1050.     blk#s  copyto: fmt_blk#s
  1051.     mark_original: fmt_blk#s    \ See, it was OK, wasn't it?
  1052.     #blks -> #fmt_blks  ;m
  1053.  
  1054.  
  1055. :m PARAS_OUT:
  1056.     para_blk#s  copyto: blk#s
  1057.     mark_original: blk#s
  1058.     reset: text  reset: para_run
  1059.     clear: para_tmp  ( 0 +w: para_tmp  0 +c: para_tmp )
  1060.     0 -> #blks  0 -> save_offs  (new_blk): self
  1061.     0 next_para
  1062.     clear: utTbl  RET selchar: utTbl  SECT selchar: utTbl
  1063.     BEGIN
  1064.         utTbl scan: text
  1065.     WHILE
  1066.         step: text  1 skip: text  text&hf_len  >lim: text
  1067.         pos: text   para_out: self
  1068.     REPEAT
  1069.     write_blk: self  save_offs hdr_len +  +L: blk#s
  1070.     blk#s  copyto: para_blk#s
  1071.     mark_original: para_blk#s
  1072.     #blks -> #para_blks   ;m
  1073.  
  1074.  
  1075. :m HDR_OUT:
  1076.     pause
  1077.     $ FE34  put: marker
  1078.     text&hf_len  hdr_len +  put: tx_end_offs
  1079.     text&hf_len  real_text_len -  ftn_len - 2-  0 max  put: hf_len
  1080.     hdr_len  put: text_start  real_text_len  put: text_length
  1081.     ftn_len  put: footnote_len
  1082.     $ 3DE0  put: paper_ht
  1083.     $ 2FD0  put: paper_wdth
  1084.     $ 5A0
  1085.     dup put: t_margin  dup put: l_margin
  1086.     dup put: b_margin      put: r_margin
  1087.     $ 2d0  put: magic3
  1088.     facing_pages?  15 <<  $ 400  or  put: page_options
  1089.     1  put: magic5  1 put: magic6
  1090.     $ A000  put: how_print?  ( tall adjusted )
  1091.     0 moveto: theFcb  OK?
  1092.     ^base  hdr_len  write: theFcb   OK?   ;m
  1093.  
  1094.  
  1095. :m FIX_FMT_BLKS:
  1096.     blk#
  1097.     #fmt_blks 0 DO
  1098.         dup  +w: fmt_blk#s  1+
  1099.     LOOP
  1100.     -> blk#
  1101.     reset: fmt_blk#s  ;m
  1102.  
  1103. :m FIX_PARA_BLKS:
  1104.     blk#
  1105.     #para_blks 0 DO
  1106.         dup  +w: para_blk#s  1+
  1107.     LOOP
  1108.     -> blk#
  1109.     reset: para_blk#s  ;m
  1110.  
  1111. :m CTRL_OUT:  { addr len -- addr' len }
  1112.     pos: buf  buf_start +  len        \ Return result
  1113.     addr len  add: buf  ;m
  1114.  
  1115. :m $CTRL_OUT:  { str -- addr' len' }
  1116.     lock: str
  1117.     all: str  ctrl_out: self
  1118.     unlock: str  ;m
  1119.  
  1120. :m NULL_CTRL:
  1121.     pos: buf  buf_start +  0  ;m
  1122.  
  1123.  
  1124. :m EXTRAS_OUT:
  1125.     pause
  1126.     buf_start  7 >> -> blk#
  1127.     fix_fmt_blks: self  fix_para_blks: self
  1128.     clear: buf  blk# 7 <<  -> buf_start
  1129.     setup_style_sheet  ( in dst )
  1130.     dst  $ctrl_out: self  release: dst
  1131.     2dup  put: styles_str1  put: styles_str2
  1132.     ftn_markers  $ctrl_out: self  put: ftn_marker_str
  1133.     ftn_offsets  $ctrl_out: self  put: ftn_offset_str
  1134.     sect_offsets  $ctrl_out: self  put: sectOffs_str
  1135.     null_ctrl: self  2dup  put: str4  2dup  put: str5  put: str6
  1136.     hf_offsets  $ctrl_out: self  put: HFOffs_str
  1137.     null_ctrl: self  put: str8
  1138.     fmt_blk#s  $ctrl_out: self  put: fmt_blk_str
  1139.     para_blk#s  $ctrl_out: self  put: para_blk_str
  1140.     for_strC  ctrl_out: self  put: strC
  1141.     null_ctrl: self  2dup  put: str9  put: change_str
  1142.     reset: buf  len: buf  buf_start +  $ 1FF +  $ FFFFFE00 and
  1143.     buf_start -  setsize: buf
  1144.     all: buf  write: theFcb  OK?
  1145. ;m
  1146.     
  1147.  
  1148. :m SEND:    \ ( fcb -- )
  1149.     -> theFcb
  1150.     setup_output: self
  1151.     update_HFs
  1152.     fixup_ftn
  1153.     fixup_HFs
  1154.     mark_sp
  1155.     text_out: self  fmts_out: self  paras_out: self
  1156.     extras_out: self  hdr_out: self
  1157.     release: buf  release: buf_offsets
  1158.     release: fmt_blk#s  release: para_blk#s
  1159.     release: para_tmp  release: hf_offsets  release: sect_offsets  ;m
  1160.     release: ftn_markers  release: ftn_offsets
  1161.  
  1162. ;class
  1163.  
  1164.  
  1165. \ Microsoft Word 4.0 documents
  1166.  
  1167.  
  1168. table    DFLT_P
  1169.     0 w,  0 w,
  1170. end_table
  1171.  
  1172.  
  1173. :class    MW4DOC    super(    object  )
  1174.  
  1175.     int    MARKER
  1176.     int    MAGIC1
  1177.     6    bytes    xx0
  1178.     int    FAST_SAVE?
  1179.     int    MAGIC2
  1180.     6    bytes    xx1
  1181.     var    TEXT_START
  1182.     var    TX_END_OFFS
  1183.     8    bytes    xx2
  1184.     var    TEXT_LENGTH
  1185.     var    FOOTNOTE_LEN
  1186.     var    HF_LEN
  1187.    16    bytes    xx3
  1188.     sd    STYLES_STR1
  1189.     sd    STYLES_STR2
  1190.     sd    FTN_MARKER_STR
  1191.     sd    FTN_OFFSET_STR
  1192.     sd    SECTOFFS_STR
  1193.     sd    StrA
  1194.     sd    Str5
  1195.     sd    Str6
  1196.     sd    HFOFFS_STR
  1197.     sd    FMT_BLK_STR
  1198.     sd    PARA_BLK_STR
  1199.     sd    Str8
  1200.     sd    StrC
  1201.     sd    StrD
  1202.     sd    Str10
  1203.     sd    PRINT_STR1
  1204.     sd    PRINT_STR2
  1205.     sd    Str11
  1206.     sd    CHANGE_STR
  1207.     sd    Str13
  1208.     int    MAGIC5
  1209.     int    MAGIC6
  1210.   68    bytes    EMPTY
  1211.     
  1212.  
  1213.  
  1214. :m CLR_BUF:
  1215.     reset: buf  all: buf  erase  ;m
  1216.  
  1217. :m SET_BUF:    \ ( blk# -- )
  1218.     theFile  copyto: buf
  1219. \    2-
  1220.     9                        \ 4
  1221.     <<
  1222.     hdr_len -                    \ 4
  1223.     dup  >pos: buf  -> buf_start
  1224.     512                        \ 4
  1225.     >len: buf
  1226.     buf copyto: buf_offsets  buf copyto: buf_tmp  ;m
  1227.  
  1228. :m BUF_OUT:
  1229.     all: buf  write: theFcb  OK?  ;m
  1230.  
  1231.  
  1232. :m SETUP_CHANGES:  { \ this_dst -- }
  1233.     clear: changes  clear: fmt_ov_str  0 -> override_marker
  1234.     fast?  0EXIT
  1235.     0 -> ov_blk#
  1236.     use: change_str  theFile copyto: tmp
  1237.     BEGIN
  1238.         len: tmp  0>  ( a bug could make it negative!!! )
  1239.     WHILE
  1240.         nxtc: tmp  ( opcode )
  1241.         2 nxtn: tmp  >len: tmp
  1242.         setup_change
  1243.         lim: theFile  >lim: tmp
  1244.     REPEAT
  1245.     reset: changes  reset: fmt_ov_str
  1246.     ^1st: changes 12 + w@  -> override_marker  ( initial value )
  1247.     find_ov_posn  ;m
  1248.  
  1249. :m TEXT_IN:
  1250.     pause
  1251.     text&HF_len  setsize: text
  1252.     fast?
  1253.     IF    change_text
  1254.     ELSE    reset: text
  1255.         get: text_start  hdr_len -  >pos: theFile  nolim: theFile
  1256.         theFile $ovwr: text  reset: text
  1257.     THEN
  1258.     text_only?  0EXIT
  1259.     real_text_len  setsize: text  reset: text  ;m
  1260.  
  1261.  
  1262. :m GET_FONT:        \ ( -- fnt# )
  1263.     options  $ 10  and
  1264.     NIF  dflt_font#  ELSE  fmt 3+ 2b@  THEN
  1265.     >nxtw: fmt_run  ;m
  1266.  
  1267. :m GET_FONTSIZE:    \ ( -- n )
  1268.     options  8 and
  1269.     NIF  12  ELSE  fmt 5 + c@  2/  THEN
  1270.     >nxtc: fmt_run  ;m
  1271.  
  1272. :m GET_FIELD:        \ ( offs -- )
  1273.     fmt + c@  ( optional field )
  1274.     >nxtc: fmt_run  ;m
  1275.  
  1276. :m GET_FMT:  { offs -- }
  1277.  
  1278.         \ Converts the current format to our internal coding
  1279.         \ and inserts it in FMT_RUN.
  1280.  
  1281.     fmt 1+ c@  -> stls  fmt 2+ c@  dup -> options
  1282.     $ 40 and  IF  offs  spec_in  EXIT  THEN
  1283.     offs new_item: fmt_run
  1284.     pos: fmt_run  -> fmt_strt
  1285.     styles styles_len  bounds
  1286.     DO    i c@  ( mask )  stls and 0<>  ( 1 set, 0 clear )
  1287.         >nxtc: fmt_run
  1288.     LOOP
  1289.     8  get_field: self  ( underline options )
  1290.     get_fontsize: self
  1291.     get_font: self
  1292.     6  get_field: self  ( vert displ )
  1293.     7  get_field: self  ( horiz displ )  ;m
  1294.  
  1295. :m (FMT_IN):  { \ offs -- }
  1296.     next_item?  0EXIT
  1297.     -> offs
  1298.     fmt  fmt_len  erase
  1299.     nxtc: buf_offsets  ?dup
  1300.     IF
  1301.         2*                    \ 4
  1302.         buf_start +  >pos: buf_tmp
  1303.         ^1st: buf_tmp  fmt  over c@ 1+  cmove
  1304.     THEN
  1305.     offs  get_fmt: self  ;m
  1306.  
  1307. :m (FMT_BLK_IN):    \ ( cnt -- )
  1308.     2 nxtn: fmt_blk#s  set_buf: self
  1309.     NIF  next_offs drop  ELSE  4 skip: buf  THEN
  1310.     last: buf  ( # formats )
  1311.     dup 1+ 4*  skip: buf_offsets
  1312.     0 ?DO    (fmt_in): self
  1313.     LOOP   ;m
  1314.  
  1315. :m FMTS_IN:
  1316.     false -> doing_paras?
  1317.     use: fmt_blk_str  setup_blks  -> #fmt_blks
  1318.     dst copyto: fmt_blk#s
  1319.     off_fmts
  1320.     #fmt_blks 0 DO  pause  i  (fmt_blk_in): self   LOOP
  1321.     merge_fmts  trim_fmt_run   ;m
  1322.  
  1323. :m GET_PARA:  { \ addr code -- }
  1324.     ^1st: para_run  -> addr
  1325.     nxtc: buf_tmp  addr w!  ;m        \ style #
  1326.  
  1327. \ We now ignore all other para info.
  1328.  
  1329.  
  1330. :m (PARA_IN):
  1331.     next_item?  0EXIT
  1332.     ( offs )  new_item: para_run
  1333.     nxtc: buf_offsets  ?dup
  1334.     IF
  1335.         2*                        \ 4
  1336.         buf_start +  >pos: buf_tmp  count: buf_tmp
  1337.         get_para: self
  1338.     THEN
  1339.     ?do_para_override
  1340.     ?keep_para   ;m
  1341.  
  1342. :m (PARA_BLK_IN):    \ ( cnt -- )
  1343.     2 nxtn: para_blk#s  set_buf: self
  1344.     NIF  next_offs drop  ELSE  4 skip: buf  THEN
  1345.     last: buf  ( # paras )
  1346.     dup 1+ 4*  skip: buf_offsets
  1347.     0 ?DO    (para_in): self
  1348.     LOOP   ;m
  1349.  
  1350. :m PARAS_IN:
  1351.     true -> doing_paras?
  1352.     use: para_blk_str  setup_blks  -> #para_blks
  1353.     dst copyto: para_blk#s
  1354.     #para_blks 0 DO  pause  i  (para_blk_in): self  LOOP   ;m
  1355.  
  1356.  
  1357. :m STYLES_IN:    \ Note: we ignore input style specifications, and just
  1358.         \ hang on to the names.
  1359.     pause
  1360.     use: styles_str2
  1361.     2 nxtn: theFile  -> #levels
  1362.     2 nxtn: theFile  2-  >len: theFile
  1363.     theFile  ->: style_names  ;m
  1364.  
  1365.  
  1366. :m HFs_IN:
  1367.     use: sectoffs_str  theFile ->: sect_offsets
  1368.     use: HFoffs_str  mark_HFs  ;m
  1369.  
  1370.  
  1371. :m FTNOTES_IN:        \ Footnotes in.  Sorry for funny name - we had
  1372.             \ a hash collision.
  1373.     ftn_len  0EXIT            \ Out if no footnotes
  1374.     use: ftn_marker_str  theFile ->: ftn_markers
  1375.     use: ftn_offset_str  theFile ->: ftn_offsets
  1376.     mark_ftn  ;m
  1377.  
  1378.  
  1379. :m SETUP_INPUT:
  1380.     pause
  1381.     new: theFile  new: changes
  1382.     new: fmt_ov_str  new: fmt_ov_run
  1383.     new: para_ov_str  new: sect_offsets  new: sect_ov_str
  1384.     new: ftn_markers  new: ftn_offsets
  1385.     false -> mystery?  0 -> #insrtd  0 -> save_offs
  1386.     ^base 2+  hdr_len 2-  read: theFcb  OK?
  1387.     get: fast_save?
  1388.     $ 2000 and  0<>                        \ 4
  1389.     -> fast?
  1390.     get: text_length  -> real_text_len
  1391.     get: tx_end_offs  hdr_len -  -> text&HF_len
  1392. \    get: page_options $ 8000 and 0<>  -> facing_pages?    \ 4
  1393.     text&HF_len  ++> mem_needed
  1394.     get: footnote_len  -> ftn_len
  1395.     text_only?  ?EXIT
  1396.     size: theFcb  hdr_len -  text&HF_len -
  1397.     3 *  0 max        \ Guesstimate for size of fmt_run etc.
  1398.     ++> mem_needed  ;m
  1399.  
  1400.  
  1401. :m INPUT_FILE:
  1402.     pause
  1403.     theFcb
  1404.     size: theFcb  hdr_len -  readn: theFile  ;m
  1405.  
  1406.  
  1407. :m FIXIT:
  1408.     setup_changes: self
  1409.     text_in: self
  1410.     text_only?
  1411.     NIF
  1412.         fmts_in: self
  1413.         paras_in: self
  1414.         styles_in: self
  1415.         ftnotes_in: self
  1416.         HFs_in: self
  1417.     THEN  ;m
  1418.  
  1419.  
  1420. :m WINDUP_INPUT:
  1421.     release: theFile  release: changes
  1422.     release: fmt_ov_str  release: fmt_ov_run
  1423.     release: para_ov_str  release: sect_offsets
  1424.     release: sect_ov_str
  1425.     release: ftn_offsets  release: ftn_markers  ;m
  1426.  
  1427.  
  1428. \ We are not including the output section as yet.
  1429.  
  1430. ;class
  1431.  
  1432.  
  1433. \ The exports - we can't export an object directly, only a colon defn.
  1434. \ So this involves a bit of fooling around.
  1435.  
  1436. MW3doc    3DOC
  1437. MW4doc  4DOC
  1438.  
  1439. : SETUP_INP3        setup_input: 3doc  ;
  1440. : SETUP_INP4        setup_input: 4doc  ;
  1441.  
  1442. : INPUT_FILE3        input_file: 3doc  ;
  1443. : INPUT_FILE4        input_file: 4doc  ;
  1444.  
  1445. : FIXIT3        fixit: 3doc  ;
  1446. : FIXIT4        fixit: 4doc  ;
  1447.  
  1448. : WINDUP_INP3        windup_input: 3doc  ;
  1449. : WINDUP_INP4        windup_input: 4doc  ;
  1450.  
  1451. : SEND3            send: 3doc  ;
  1452.  
  1453. : (STR_OUT)    str_out: 3doc  ;
  1454.